new Vue({

  el: '#app',

  data: {
    name: null,
    ip: null,
    openVideo: true,
    isCalling: false,
    ws: null,
    peerConnection: null,
    constraints: null,
    server: null,
  },

  computed: {
    isPrepared() {
      return (this.name !== '') && (this.name !== null) && (this.ws !== null);
    }
  },

  mounted () {
    if (!this._isSupportWebRTC()) {
      return alert('你不支持 WebRTC 通话');
    }

    this.constraints = {
      audio: true,
      video: {
        width: window.innerWidth,
        height: window.innerHeight,
      },
    };

    // const localVideo = this.$refs.localVideo;
    // navigator.mediaDevices.getUserMedia(this.constraints)
    //   .then(stream => localVideo.srcObject = stream)
    //   .catch(err => console.error('ERROR', err));

    this.server = {
      iceServers: [
        { urls: 'stun:stun1.l.google.com:19302' },
        { urls: 'stun:stun2.l.google.com:19302' },
        { urls: 'stun:stun3.l.google.com:19302' },
        { urls: 'stun:stun4.l.google.com:19302' },
      ],
    };

    this.name = '游客' + Math.random().toString(16).substr(2, 6);

    this.ws = new WebSocket('wss://dev.wecareroom.com/websocket');

    this.ws.onmessage = async e => {
      const { id, type, data } = JSON.parse(e.data);
      if (id !== this.name && type === 'offer') {
        this._trace('Received offer');
        this._onCalled(data);
      }
      if (id !== this.name && type === 'answer') {
        this._trace('Received answer');
        await this.peerConnection.setRemoteDescription(new RTCSessionDescription(data));
      }
      if (id !== this.name && type === 'candidate') {
        this._trace('Received candidate', data);
        if (this.peerConnection !== null) {
          await this.peerConnection.addIceCandidate(new RTCIceCandidate(data));
        }
      }
    };
  },

  methods: {

    switchMode() {
      this.openVideo = !this.openVideo;
      if (this.openVideo) {
        this.constraints = {
          audio: false,
          video: {
            width: window.innerWidth,
            height: window.innerHeight,
          },
        };
      } else {
        this.constraints = {
          audio: true,
          video: false,
        };
      }
    },

    async onCallOut() {
      this.isCalling = true;
      await this._prepareLocalStreamAndPeerConnection();
      // create offer
      // set local description
      // send offer
      const offer = await this.peerConnection.createOffer();
      await this.peerConnection.setLocalDescription(new RTCSessionDescription(offer));
      this._sendMessage('offer', offer);
      this._trace('Send offer')
    },

    onHungUp() {
      this.isCalling = false;
      window.reload();
    },

    async _onCalled(offer) {
      if (!window.confirm('有新的来电，是否接听')) {
        return;
      }
      this.isCalling = true;
      await this._prepareLocalStreamAndPeerConnection();
      // set remote description
      // create answer
      // set local description
      // send answer
      await this.peerConnection.setRemoteDescription(new RTCSessionDescription(offer));
      const answer = await this.peerConnection.createAnswer();
      await this.peerConnection.setLocalDescription(new RTCSessionDescription(answer));
      const data = { id: this.name, type: 'answer', data: answer };
      this._sendMessage('answer', answer);
      this._trace('Send answer');
    },

    _sendMessage(type, data) {
      if (this.ws) {
        const wrappedData = { id: this.name, type, data };
        const transformData = JSON.stringify(wrappedData);
        this.ws.send(transformData);
      }
    },

    async _prepareLocalStreamAndPeerConnection() {
      const localVideo = this.$refs.localVideo;
      const remoteVideo = this.$refs.remoteVideo;
      // create local stream
      const localStream = await navigator.mediaDevices.getUserMedia(this.constraints);
      localVideo.srcObject = localStream;
      // create peer connection
      // listen the remote stream added
      // then play the remote stream
      this.peerConnection = this.peerConnection || new RTCPeerConnection(this.server);
      this.peerConnection.onicecandidate = event => {
        if (event.candidate) {
          this._trace('send candidate', event.candidate);
          const iceCandidate = new RTCIceCandidate(event.candidate);
          this._sendMessage('candidate', iceCandidate);
        }
      };
      this.peerConnection.ontrack = event => {
        if (event.track) {
          this._trace('remote track', event);
          if (remoteVideo.srcObject === null) {
            remoteVideo.srcObject = new MediaStream([event.track]);
          } else {
            remoteVideo.srcObject.addTrack(event.track);
          }
        }
      };
      // add local stream to peer connection
      // prepare to send
      this._trace('local stream');
      localStream.getTracks().forEach(track => this.peerConnection.addTrack(track));
      // this.peerConnection.addStream(localStream);
    },

    _trace(...messages) {
      const now = new Date();
      console.log(`[${now.toLocaleTimeString()}.${now.getMilliseconds()} CLIENT]:`, ...messages);
    },

    _isSupportWebRTC() {
      const getUserMediaAPI = navigator.mediaDevices && navigator.mediaDevices.getUserMedia;
      const webRTCAPI = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection;
      return getUserMediaAPI !== undefined && webRTCAPI !== undefined;
    }

  },

});
